package code.example.base.util.concurrent.container;

import code.example.tool.LogFactory;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 *
 * 使用 cas + Locksupport 实现支持并发的队列
 *
 * 内部采用单向链表  Head-->Node-->node-->Tail
 */
public class ConcurrentLinkNodes<E> {
    volatile Node head  = new Node(),tail=head;


    private static AtomicReferenceFieldUpdater headUpdater = AtomicReferenceFieldUpdater.newUpdater(ConcurrentLinkNodes.class,Node.class,"head");
    private static AtomicReferenceFieldUpdater tailUpdater = AtomicReferenceFieldUpdater.newUpdater(ConcurrentLinkNodes.class,Node.class,"tail");

    private  boolean setTail(Node tail,Node newTail){
       return tailUpdater.compareAndSet(this,tail,newTail);
    }
    private boolean setHead(Node head,Node newHead){

        boolean result =  headUpdater.compareAndSet(this,head,newHead);
        if(result ){//成功设置result
           // head.next = head;//help gc
        }
        return result;
    }
    public ConcurrentLinkNodes(){
       /* head.next = tail;*/
    }
    public void offer(E e){
        Node<E> newNode =new Node<E>();
        newNode.set(e);
        Node ct,t;

        restart:
        for(;;){
            for(ct = t = tail;;t = t.next){

                if(t.next != null){
                    continue;
                }else if(t.setNext(null,newNode)){
                    setTail(ct,newNode);
                    break restart;
                }else{
                    continue restart;
                }
            }
        }

    }
    public E poll(){

        restart:
        for(;;){

            for(Node<E> head=this.head, current= head;current != null;current = current.next){


                E item = current.get();
                if(item == null){//没有对象保存
                    if( current.next ==current){//head 被重置了，重新开始
                        continue restart;
                    }else{//对象已被取出了，循环找下一个节点
                        continue;
                    }
                }else{//有对象保存
                    if(current.setObj(item,null)){//置为空成功
                        this.setHead(head,current);
                        return item;//返回
                    }else{//有其它线程取走了，重新开始
                        continue restart;
                    }
                }
            }
            return null;
        }

    }
}
